#include <gtest/gtest.h>
#include "file_manager.h"
#include "utils_log.h"
#include <fstream>
#include <thread>
#include <filesystem>
#include <chrono>
#include <future>

#include "nlohmann/json.hpp"
#include "utils_init.h"
#include "common_init.h"

namespace El {
namespace FileManager {

class FileManagerTest : public ::testing::Test {
protected:
    static void SetUpTestSuite()
    {
        // 初始化基础库
        nlohmann::json config;
        config["log_level"] = "info";
        config["log_to_file"] = false;
        El::Utils::base_init(config);
        
        // 初始化配置
        config.clear();
        config["general"] = "/mnt/config/config";
        config["default"] = "/mnt/config/default";
        config["product"] = "/app/custom/product.yaml";
        El::Common::common_init(config);

        // 初始化文件管理器
        EXPECT_TRUE(IFileManager::GetInstance().Start());
    }

    static void TearDownTestSuite()
    {
        // 清理测试生成的文件
        // 注意：实际测试中可能需要更复杂的清理逻辑
    }

    // 创建临时文件工具函数
    std::string CreateTempFile(const std::string &fileName, const std::string &content)
    {
        std::ofstream file(fileName, std::ios::binary);
        file << content;
        file.close();
        return fileName;
    }
};

TEST_F(FileManagerTest, CreateFileTest)
{
    std::string fileName = "test_audio.wav";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::AUDIO);
    EXPECT_FALSE(fileId.empty());
}

TEST_F(FileManagerTest, GetFileInfoTest)
{
    // 先创建一个文件
    std::string fileName = "test_info.mp3";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::AUDIO);
    EXPECT_FALSE(fileId.empty());

    // 写入文件内容，使文件被添加到索引中
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, "测试数据", true));

    // 获取文件信息
    FileInfo fileInfo;
    EXPECT_TRUE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
    EXPECT_EQ(fileInfo.name, fileName);
    EXPECT_EQ(fileInfo.type, "audio");
}

TEST_F(FileManagerTest, WriteFileBlockTest)
{
    // 创建一个新文件
    std::string fileName = "test_write.jpg";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::IMAGE);
    EXPECT_FALSE(fileId.empty());

    // 写入文件内容
    std::string content = "测试文件内容";
    bool result = IFileManager::GetInstance().WriteFileBlock(fileId, content, true);
    EXPECT_TRUE(result);

    // 获取文件信息验证
    FileInfo fileInfo;
    EXPECT_TRUE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
    EXPECT_EQ(fileInfo.size, content.size());
}

TEST_F(FileManagerTest, DeleteFileTest)
{
    // 创建一个新文件
    std::string fileName = "test_delete.mp4";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::VIDEO);
    EXPECT_FALSE(fileId.empty());

    // 写入一些内容
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, "测试数据", true));

    // 删除文件
    EXPECT_TRUE(IFileManager::GetInstance().DeleteFile(fileId));

    // 用户文件被物理删除后，GetFileInfo应该返回false
    FileInfo fileInfo;
    EXPECT_FALSE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
}

TEST_F(FileManagerTest, RestoreFileTest)
{
    // 创建并删除一个预制文件，而不是用户文件
    // 修改测试逻辑：创建一个文件后检查其路径是否在预制目录中，不是的话这个测试就不适用
    std::string fileName = "test_restore.wav";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::AUDIO);
    EXPECT_FALSE(fileId.empty());
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, "测试数据", true));
    
    // 获取文件信息，检查是否为预制文件
    FileInfo fileInfo;
    EXPECT_TRUE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
    
    // 由于这是一个用户创建的文件，它不应该是预制文件
    // 判断恢复操作应该失败
    EXPECT_TRUE(IFileManager::GetInstance().DeleteFile(fileId));
    EXPECT_FALSE(IFileManager::GetInstance().RestoreFile(fileId));

    // 用户文件无法被恢复，GetFileInfo应该返回false
    EXPECT_FALSE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
}

TEST_F(FileManagerTest, GetFileListTest)
{
    // 创建几个不同类型的文件
    std::string audioId = IFileManager::GetInstance().CreateFile("test_list_audio.wav", FileType::AUDIO);
    std::string imageId = IFileManager::GetInstance().CreateFile("test_list_image.jpg", FileType::IMAGE);
    std::string videoId = IFileManager::GetInstance().CreateFile("test_list_video.mp4", FileType::VIDEO);

    // 写入内容
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(audioId, "audio data", true));
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(imageId, "image data", true));
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(videoId, "video data", true));

    // 获取所有文件列表
    std::vector<FileInfo> allFiles = IFileManager::GetInstance().GetFileList(FileType::ALL);
    EXPECT_GE(allFiles.size(), 3);

    // 获取音频文件列表
    std::vector<FileInfo> audioFiles = IFileManager::GetInstance().GetFileList(FileType::AUDIO);
    EXPECT_GE(audioFiles.size(), 1);

    // 获取图片文件列表
    std::vector<FileInfo> imageFiles = IFileManager::GetInstance().GetFileList(FileType::IMAGE);
    EXPECT_GE(imageFiles.size(), 1);

    // 获取视频文件列表
    std::vector<FileInfo> videoFiles = IFileManager::GetInstance().GetFileList(FileType::VIDEO);
    EXPECT_GE(videoFiles.size(), 1);
}

TEST_F(FileManagerTest, MultipleBlockWriteTest)
{
    // 创建一个新文件
    std::string fileName = "test_multi_block.mp4";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::VIDEO);
    EXPECT_FALSE(fileId.empty());

    // 写入多个数据块
    std::string block1 = "第一块数据";
    std::string block2 = "第二块数据";
    std::string block3 = "第三块数据";

    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, block1, false));
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, block2, false));
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, block3, true));

    // 验证文件大小
    FileInfo fileInfo;
    EXPECT_TRUE(IFileManager::GetInstance().GetFileInfo(fileId, fileInfo));
    EXPECT_EQ(fileInfo.size, block1.size() + block2.size() + block3.size());
}

TEST_F(FileManagerTest, GetFilePathTest)
{
    // 创建一个新文件
    std::string fileName = "test_path.wav";
    std::string fileId = IFileManager::GetInstance().CreateFile(fileName, FileType::AUDIO);
    EXPECT_FALSE(fileId.empty());

    // 写入内容
    EXPECT_TRUE(IFileManager::GetInstance().WriteFileBlock(fileId, "test data", true));

    // 获取文件路径
    std::string filePath = IFileManager::GetInstance().GetFilePath(fileId);
    EXPECT_FALSE(filePath.empty());

    // 验证文件存在
    EXPECT_TRUE(std::filesystem::exists(filePath));
}

} // namespace FileManager
} // namespace El
